//===============================================================================
// Microsoft patterns & practices
// Web Client Software Factory
//-------------------------------------------------------------------------------
// Copyright (C) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//-------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================
using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.Activities;
using System.Collections.ObjectModel;
using System.Workflow.Runtime;
using System.Workflow.ComponentModel;
using System.Threading;

namespace WCSFContrib.PageFlow.WorkflowFoundation
{
	/// <summary>
	/// Provides a mechanism for retrieving information about a 
	/// <see cref="WorkflowInstance">WorkflowInstance</see>.
	/// </summary>
    public class StateMachineQuery
    {
        private StateMachineWorkflowActivity _definition;
        private WorkflowInstance _instance;

		/// <summary>
		/// Creates an instance of a StateMachineQuery.
		/// </summary>
		/// <param name="definition">The definitaion of the workflow.</param>
		/// <param name="instance">A Workflow instance.</param>
        public StateMachineQuery(StateMachineWorkflowActivity definition, WorkflowInstance instance)
        {
            _definition = definition;
            _instance = instance;
        }

		/// <summary>
		/// Gets the current state of the Workflow.
		/// </summary>
        public StateActivity CurrentState
        {
            get
            {
                return this.GetCurrentState();
            }
        }

		/// <summary>
		/// Gets the name of the current Workflow state.
		/// </summary>
        public string CurrentStateName
        {
            get
            {
                StateActivity current = this.CurrentState;
                if (current == null)
                {
                    return null;
                }
                return current.QualifiedName;
            }
        }
		
		/// <summary>
		/// Notifies the caller if there is data available in the Workflow queue.
		/// </summary>
		/// <returns>True when </returns>
        public bool IsWorkflowQueueDataAvailable()
        {
            return _instance.GetWorkflowQueueData().Count > 0;
        }

		/// <summary>
		/// Sets the state on the Workflow.
		/// </summary>
		/// <param name="targetStateName">The name of the state to set as the Workflow's current state.</param>
        public void SetState(string targetStateName)
        {
            if (targetStateName == null)
            {
                throw new ArgumentNullException("targetStateName");
            }
            if (!(FindActivityByName(_definition, targetStateName) is StateActivity))
            {
                throw new ArgumentOutOfRangeException("targetStateName");
            }
            SetStateEventArgs setStateArgs = new SetStateEventArgs(targetStateName);
            _instance.EnqueueItemOnIdle("SetStateQueue", setStateArgs, null, null);
        }

        private StateActivity FindStateByName(StateActivity state, string qualifiedName)
        {
            return FindActivityByName(state, qualifiedName) as StateActivity;
        }

        private Activity FindActivityByName(CompositeActivity parentActivity, string qualifiedName)
        {
            return parentActivity.GetActivityByName(qualifiedName, true);
        }

		private StateActivity GetCurrentState()
		{
			ReadOnlyCollection<WorkflowQueueInfo> workflowQueueInfos = _instance.GetWorkflowQueueData();
			using (IEnumerator<WorkflowQueueInfo> enumerator = workflowQueueInfos.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					WorkflowQueueInfo queueInfo = enumerator.Current;
					if (queueInfo.QueueName.Equals("SetStateQueue"))
					{
						if (queueInfo.SubscribedActivityNames.Count == 0)
						{
							return null;
						}
						return FindStateByName(_definition, queueInfo.SubscribedActivityNames[0]);
					}
				}
			}
			return null;
		}
    }
}
